﻿using Model;
using Model.Auxiliar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BLL
{
    public class Funcionario_BLL
    {
        #region singleton
        private static Funcionario_BLL instance;

        private Funcionario_BLL() { }

        public static Funcionario_BLL Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Funcionario_BLL();
                }
                return instance;
            }
        }
        #endregion



        public List<hrp_funcionario> ObterListaFuncionario(int id_cliente, int id_empresa, int id_dep, int id_cargo, bool apenasActivos)
        {
            hrpEntities hrp = new hrpEntities();
            var funcList = from func in hrp.hrp_funcionario
                           join cargo in hrp.hrp_cargos on func.id_cargo equals cargo.id into funcCargoView
                           from funcCargo in funcCargoView
                           where func.id_cliente == id_cliente && func.id_empresa == id_empresa
                            && (id_dep == 0 || (id_dep != 0 && funcCargo.id_departamento == id_dep))
                            && (id_cargo == 0 || (id_cargo != 0 && funcCargo.id == id_cargo))
                            && (!apenasActivos || (apenasActivos && func.activo.Value))
                           select func;
            return funcList.ToList();
        }

        public bool FuncionarioExiste(int id_cliente, int id_empresa, int id_funcionario)
        {
            hrpEntities hrp = new hrpEntities();
            return hrp.hrp_funcionario.Any(f => f.id == id_funcionario && f.id_cliente == id_cliente && f.id_empresa == id_empresa);
        }



        public hrp_funcionario ObterFuncionarioPorId(int id_cliente, int id_empresa, int id_funcionario)
        {
            hrpEntities hrp = new hrpEntities();
            var funcList = from funcionario in hrp.hrp_funcionario
                           where funcionario.id == id_funcionario && funcionario.id_cliente == id_cliente && funcionario.id_empresa == id_empresa
                           select funcionario;
            return funcList.FirstOrDefault();
        }

        public hrp_funcionario ObterFuncionarioPorId1(int id_funcionario)
        {
            hrpEntities hrp = new hrpEntities();
            var funcList = from funcionario in hrp.hrp_funcionario
                           where funcionario.id == id_funcionario
                           select funcionario;
            return funcList.FirstOrDefault();
        }

        //Todo: Ver contratos e salarios desactivados
        public Funcionario ObterFuncionario(int id_cliente, int id_empresa, int id_funcionario)
        {
            hrpEntities hrp = new hrpEntities();
            var funcList = from funcionario in hrp.hrp_funcionario
                           join contrato in hrp.hrp_contratos on funcionario.id equals contrato.id_funcionario
                           join salario in hrp.hrp_salario on contrato.id equals salario.id_contrato
                           join cargo in hrp.hrp_cargos on funcionario.id_cargo equals cargo.id
                           join departamento in hrp.hrp_departamentos on cargo.id_departamento equals departamento.id
                           where funcionario.id == id_funcionario && funcionario.id_cliente == id_cliente && funcionario.id_empresa == id_empresa
                           && contrato.activo.Value && salario.activo
                           select new Funcionario
                           {
                               Dados = funcionario,
                               Departamento = departamento,
                               Cargo = cargo,
                               Contrato = contrato,
                               Salario = salario,
                           };

            var func = funcList.FirstOrDefault();
            if (func != null)
            {
                func.Faltas = hrp.hrp_faltas.Any(f => f.id_funcionario == func.Dados.id) ? hrp.hrp_faltas.Where(f => f.id_funcionario == func.Dados.id).ToList() : new List<hrp_faltas>();
                func.HorasExtras = hrp.hrp_horasextra.Any(h => h.id_funcionario == func.Dados.id) ? hrp.hrp_horasextra.Where(h => h.id_funcionario == func.Dados.id).ToList() : new List<hrp_horasextra>();

            }
            return func;
        }

        private void CriarLog(hrpEntities hrp, ref hrp_funcionario actualFuncionario, string userId, string userIp, DateTime userTimestamp)
        {
            hrp_funcionario_log funcLog = new hrp_funcionario_log();
            funcLog.activo = actualFuncionario.activo;
            funcLog.codigo_postal = actualFuncionario.codigo_postal;
            funcLog.email = actualFuncionario.email;
            funcLog.foto = actualFuncionario.foto;
            funcLog.iban = actualFuncionario.iban;
            funcLog.id = actualFuncionario.id;
            funcLog.id_cargo = actualFuncionario.id_cargo;
            funcLog.id_cliente = actualFuncionario.id_cliente;
            funcLog.id_empresa = actualFuncionario.id_empresa;
            funcLog.log_user_id = userId;
            funcLog.log_user_ip = userIp;
            funcLog.log_user_timestamp = userTimestamp;
            funcLog.morada = actualFuncionario.morada;
            funcLog.nib = actualFuncionario.nib;
            funcLog.nif = actualFuncionario.nif;
            funcLog.nome = actualFuncionario.nome;
            funcLog.numero_funcionario = actualFuncionario.numero_funcionario;
            funcLog.obs = actualFuncionario.obs;
            funcLog.pais = actualFuncionario.pais;
            funcLog.pais_iso = actualFuncionario.pais_iso;
            funcLog.ss = actualFuncionario.ss;
            funcLog.telefone = actualFuncionario.telefone;
            funcLog.telemovel = actualFuncionario.telemovel;
            funcLog.user_id = actualFuncionario.user_id;
            funcLog.user_ip = actualFuncionario.user_ip;
            funcLog.user_timestamp = actualFuncionario.user_timestamp;
            hrp.hrp_funcionario_log.Add(funcLog);
        }

        public void ActualizarFuncionario(int funcionarioId, int client_id, string userid, string ip, string nome, string morada, string codigo_postal,
           string pais, int isopais, string telefone, string telemovel, string email, string nib, string iban,
           int id_cargo, int numero_funcionario, string obs, string foto, int id_empresa, double nif, double ss)
        {

            try
            {
                DateTime timestamp = DateTime.Now;
                hrpEntities hrp = new hrpEntities();
                hrp_funcionario actualFuncionario = hrp.hrp_funcionario.FirstOrDefault(f => f.id == funcionarioId && f.id_cliente == client_id && f.id_empresa == id_empresa);
                CriarLog(hrp, ref actualFuncionario, userid, "", timestamp);
                actualFuncionario.id_cliente = client_id;
                actualFuncionario.user_id = userid;
                actualFuncionario.user_timestamp = timestamp;
                actualFuncionario.user_ip = ip;
                actualFuncionario.nome = nome;
                actualFuncionario.morada = morada;
                actualFuncionario.codigo_postal = codigo_postal;
                actualFuncionario.pais = pais;
                actualFuncionario.pais_iso = isopais;
                actualFuncionario.telefone = telefone;
                actualFuncionario.telemovel = telemovel;
                actualFuncionario.email = email;
                actualFuncionario.nib = nib;
                actualFuncionario.iban = iban;
                actualFuncionario.id_cargo = id_cargo;
                actualFuncionario.activo = true;
                actualFuncionario.numero_funcionario = numero_funcionario;
                actualFuncionario.obs = obs;
                actualFuncionario.foto = foto;
                actualFuncionario.id_empresa = id_empresa;
                actualFuncionario.nif = nif;
                actualFuncionario.ss = ss;
                hrp.SaveChanges();
            }
            catch (Exception)
            {
                throw;
            }
        }

        public int inserirFuncionario(int client_id, string userid, string ip, string nome, string morada, string codigo_postal,
            string pais, int isopais, string telefone, string telemovel, string email, string nib, string iban,
            int id_cargo, int numero_funcionario, string obs, string foto, int id_empresa, double nif, double ss)
        {

            int result = 0;
            try
            {
                hrpEntities hrp = new hrpEntities();
                hrp_funcionario inserirNovoFuncionario = new hrp_funcionario();
                inserirNovoFuncionario.id_cliente = client_id;
                inserirNovoFuncionario.user_id = userid;
                inserirNovoFuncionario.user_timestamp = DateTime.Now;
                inserirNovoFuncionario.user_ip = ip;
                inserirNovoFuncionario.nome = nome;
                inserirNovoFuncionario.morada = morada;
                inserirNovoFuncionario.codigo_postal = codigo_postal;
                inserirNovoFuncionario.pais = pais;
                inserirNovoFuncionario.pais_iso = isopais;
                inserirNovoFuncionario.telefone = telefone;
                inserirNovoFuncionario.telemovel = telemovel;
                inserirNovoFuncionario.email = email;
                inserirNovoFuncionario.nib = nib;
                inserirNovoFuncionario.iban = iban;
                inserirNovoFuncionario.id_cargo = id_cargo;
                inserirNovoFuncionario.activo = true;
                inserirNovoFuncionario.numero_funcionario = numero_funcionario;
                inserirNovoFuncionario.obs = obs;
                inserirNovoFuncionario.foto = foto;
                inserirNovoFuncionario.id_empresa = id_empresa;
                inserirNovoFuncionario.nif = nif;
                inserirNovoFuncionario.ss = ss;

                hrp.hrp_funcionario.Add(inserirNovoFuncionario);
                hrp.SaveChanges();
                result = inserirNovoFuncionario.id;
            }
            catch (Exception)
            {
                throw;
            }
            return result;
        }


        public bool verificarFuncionarioExiste(string nomeFuncionario, int id_empresa)
        {
            hrpEntities hrp = new hrpEntities();
            var funcionario = from funcionarios in hrp.hrp_funcionario
                              where funcionarios.nome == nomeFuncionario && funcionarios.id_empresa == id_empresa
                              select funcionarios;

            return funcionario.Any();
        }



        public hrp_cargos obterCargoFuncionario(int id_cargo)
        {
            hrpEntities hrp = new hrpEntities();
            var cargo = from cargos in hrp.hrp_cargos
                        where cargos.id == id_cargo
                        select cargos;

            return cargo.FirstOrDefault();
        }

        public int atribuirSalario(int idcliente, string userid, string ip, int id_funcionario, decimal salario,
             string nomepais, int isopais, int id_empresa, string moeda, decimal ajudas)
        {
            int result = 0;
            try
            {
                hrpEntities hrp = new hrpEntities();
                hrp_salario novoSalarioFuncionario = new hrp_salario();

                novoSalarioFuncionario.id_cliente = idcliente;
                novoSalarioFuncionario.user_id = userid;
                novoSalarioFuncionario.user_ip = ip;
                novoSalarioFuncionario.user_timestamp = DateTime.Now;
                novoSalarioFuncionario.id_funcionario = id_funcionario;
                novoSalarioFuncionario.id_empresa = id_empresa;
                novoSalarioFuncionario.iso_pais = isopais;
                novoSalarioFuncionario.pais = nomepais;
                novoSalarioFuncionario.moedaShort = moeda;
                novoSalarioFuncionario.ajudas = ajudas;
                novoSalarioFuncionario.salario = salario;
                hrp.hrp_salario.Add(novoSalarioFuncionario);
                hrp.SaveChanges();
                result = novoSalarioFuncionario.id;
            }
            catch (Exception)
            {

                throw;
            }

            return result;
        }


        

        public void activar_desactivarFuncionario(int id_funcionario)
        {

            hrpEntities hrp = new hrpEntities();
            hrp_funcionario funcionario = hrp.hrp_funcionario.FirstOrDefault(f => f.id == id_funcionario);
            funcionario.activo = !funcionario.activo;
            hrp.SaveChanges();
        }

        public bool updateFotoFuncionario(int id_funcionario, string foto)
        {
            hrpEntities hrp = new hrpEntities();
            hrp_funcionario funcionario = hrp.hrp_funcionario.Where(f => f.id == id_funcionario).FirstOrDefault();
            if (funcionario != null)
            {
                funcionario.foto = foto;
                hrp.SaveChanges();
                return true;
            }
            return false;
        }

        public hrp_contratos ObterContratoFuncionario(int id_funcionario)
        {
            hrpEntities hrp = new hrpEntities();
            var result = from contrato in hrp.hrp_contratos
                         join salario in hrp.hrp_salario on contrato.id equals salario.id_contrato
                         where contrato.activo.Value && salario.activo && contrato.id_funcionario == id_funcionario
                         select contrato;

            return result.FirstOrDefault();
        }


        public List<hrp_adiantamentos> obterAdiantamentosFuncionario(int id_funcionario)
        {
            hrpEntities hrp = new hrpEntities();
            return hrp.hrp_adiantamentos.Where(c => c.id_funcionario == id_funcionario && c.estado).ToList();
        }

        public int registarAdiantamento(string userid, string ip, int id_funcionario, DateTime user_timestamp,
             string obs, int mes, int ano, decimal valor, bool estado, string modoPagamento)
        {
            int result = 0;
            try
            {
                hrpEntities hrp = new hrpEntities();
                hrp_adiantamentos novoAdiantamento = new hrp_adiantamentos();
                novoAdiantamento.user_id = userid;
                novoAdiantamento.user_timestamp = DateTime.Now;
                novoAdiantamento.user_ip = ip;
                novoAdiantamento.ano = ano;
                novoAdiantamento.descricao = obs;
                novoAdiantamento.estado = estado;
                novoAdiantamento.id_funcionario = id_funcionario;
                novoAdiantamento.mes = mes;
                novoAdiantamento.modo_pagamento = modoPagamento;
                novoAdiantamento.valor = valor;

                hrp.hrp_adiantamentos.Add(novoAdiantamento);
                hrp.SaveChanges();
                result = novoAdiantamento.id;
            }
            catch (Exception)
            {

                throw;
            }

            return result;
        }
        public void CancelarAdiantamentos(int id_adiantamento, bool estado, string userid, string ip)
        {
            hrpEntities hrp = new hrpEntities();
            DateTime dataActual = DateTime.Now;

            var adiantamento = hrp.hrp_adiantamentos.FirstOrDefault(a => a.id == id_adiantamento);
            hrp_adiantamentos_log adiantamentoLog = new hrp_adiantamentos_log();
            adiantamentoLog.ano = adiantamento.ano;
            adiantamentoLog.descricao = adiantamento.descricao;
            adiantamentoLog.estado = adiantamento.estado;
            adiantamentoLog.id_adiantamento = adiantamento.id;
            adiantamentoLog.id_funcionario = adiantamento.id_funcionario;
            adiantamentoLog.log_user_id = userid;
            adiantamentoLog.log_user_ip = ip;
            adiantamentoLog.log_user_timestamp = dataActual;
            adiantamentoLog.mes = adiantamento.mes;
            adiantamentoLog.modo_pagamento = adiantamento.modo_pagamento;
            adiantamentoLog.user_id = adiantamento.user_id;
            adiantamentoLog.user_ip = adiantamento.user_ip;
            adiantamentoLog.user_timestamp = adiantamentoLog.user_timestamp;
            adiantamentoLog.valor = adiantamentoLog.valor;
            hrp.hrp_adiantamentos_log.Add(adiantamentoLog);

            adiantamento.estado = estado;
            adiantamento.user_id = userid;
            adiantamento.user_ip = ip;
            adiantamento.user_timestamp = dataActual;
            hrp.SaveChanges();
        }

        public hrp_adiantamentos ObterAdiantamento(int id)
        {
            hrpEntities hrp = new hrpEntities();
            return hrp.hrp_adiantamentos.FirstOrDefault(a => a.id == id);
        }

        public List<hrp_adiantamentos_tipo> obterTiposAdiantamento()
        {
            hrpEntities hrp = new hrpEntities();
            return hrp.hrp_adiantamentos_tipo.Where(c => c.active == true).ToList();
        }

    }
}
